﻿using NUnit.Framework;
using SymbolIntegration.core.Helpers;

namespace SymbolIntegration.test
{
    [TestFixture]
    public class ExpressionTest
    {
        [TestCase("x", "X")]
        [TestCase("x^y + 12*u*u - r", "R")]
        [TestCase("x^y + 12*u*u - r", "i")]
        [TestCase("sin(m)*cos(r^3 - 12)", "sin")]
        [TestCase("sin(m)*cos(r^3 - 12)", "cos")]
        [TestCase("cos * 3 - sin(x)", "sin")]
        [TestCase("cos * 3 - sin(x)", "3")]
        [TestCase("x", "y")]
        [Test]
        public void IsDependsFrom_False_Test(string expressionText, string variable)
        {
            var expression = ParseUtils.ParseExpression(expressionText);
            Assert.IsFalse(expression.IsDependsFrom(variable));
        }

        [TestCase("x", "x")]
        [TestCase("x^y + 12*u*u - r", "y")]
        [TestCase("x^y + 12*u*u-i - r", "i")]
        [TestCase("sin(cos(7*m))*cos(r^3 - 12)", "m")]
        [TestCase("sin(m)*cos(r^3 - 12)", "r")]
        [TestCase("cos * 3 - sin(x)", "cos")]
        [TestCase("x^s^3^4^5*5+3+4-y", "y")]
        [Test]
        public void IsDependsFrom_True_Test(string expressionText, string variable)
        {
            var expression = ParseUtils.ParseExpression(expressionText);
            Assert.IsTrue(expression.IsDependsFrom(variable));
        }

        [TestCase("x", true)]
        [TestCase("x^y + 12*u*u - r", true)]
        [TestCase("-(x^y + 12*u*u-i - r)", false)]
        [TestCase("-sin(cos(7*m))*cos(r^3 - 12)", true)]
        [TestCase("-sin(m)", false)]
        [TestCase("cos * 3 - sin(x)", true)]
        [TestCase("-5", false)]
        [Test]
        public void InvertNegate_MakesNegateExpression_Test(string expressionText, bool isNegate)
        {
            var expression = ParseUtils.ParseExpression(expressionText);
            expression = expression.InvertNegate(isNegate);
            Assert.IsTrue(expression.IsNegate);
        }

        [TestCase("-x", true)]
        [TestCase("x^y + 12*u*u - r", false)]
        [TestCase("x", false)]
        [TestCase("x^y + 12*u*u - r", false)]
        [TestCase("-(x^y + 12*u*u-i - r)", true)]
        [TestCase("-sin(cos(7*m))*cos(r^3 - 12)", false)]
        [TestCase("-sin(m)", true)]
        [TestCase("cos * 3 - sin(x)", false)]
        [TestCase("-5", true)]
        [Test]
        public void InvertNegate_MakesNotNegateExpression_Test(string expressionText, bool isNegate)
        {
            var expression = ParseUtils.ParseExpression(expressionText);
            expression = expression.InvertNegate(isNegate);
            Assert.IsFalse(expression.IsNegate);
        }

        [TestCase("x", "X")]
        [TestCase("x + 3", "x * 3")]
        [TestCase("x - 3", "x + 3")]
        [TestCase("x - 3", "-x - 3")]
        [TestCase("x*y", "-x - 3")]
        [TestCase("x*i*i", "x*i*x")]
        [TestCase("x/i*i", "x*i*i")]
        [TestCase("x^i^i", "x*i^i")]
        [TestCase("x", "x")]
        [TestCase("y - 3", "y - 3")]
        [TestCase("3  - y", "-y + 3")]
        [TestCase("3  + y", "y + 3")]
        [TestCase("3  + y + x * n * y * (12 + e)", "y  + 3 +  n *(12 + e) * x* y")]
        [Test]
        public void IsEqual_ForDifferentsOrder_Equal_Test(string expressionTextLeft, string expressionTextRight)
        {
            var expressionLeft = ParseUtils.ParseExpression(expressionTextLeft);
            var expressionRight = ParseUtils.ParseExpression(expressionTextRight);
            Assert.AreEqual(expressionLeft.IsEqual(expressionRight), expressionRight.IsEqual(expressionLeft));
        }

        [TestCase("x", "X")]
        [TestCase("y - 3", "x - 3")]
        [TestCase("x + 3", "x * 3")]
        [TestCase("x - 3", "x + 3")]
        [TestCase("x - 3", "-x - 3")]
        [TestCase("x*y", "-x - 3")]
        [TestCase("x*i*i", "x*i*x")]
        [TestCase("x/i*i", "x*i*i")]
        [TestCase("x^i^i", "x*i^i")]
        [Test]
        public void IsEqual_DifferentExpressions_False_Test(string expressionTextLeft, string expressionTextRight)
        {
            var expressionLeft = ParseUtils.ParseExpression(expressionTextLeft);
            var expressionRight = ParseUtils.ParseExpression(expressionTextRight);
            Assert.IsFalse(expressionLeft.IsEqual(expressionRight));
        }

        [TestCase("x", "x")]
        [TestCase("y - 3", "y - 3")]
        [TestCase("3  - y", "-y + 3")]
        [TestCase("3  + y", "y + 3")]
        [TestCase("3  + y + x * n * y * (12 + e)", "y  + 3 +  n *(12 + e) * x* y")]
        [Test]
        public void IsEqual_DifferentExpressions_True_Test(string expressionTextLeft, string expressionTextRight)
        {
            var expressionLeft = ParseUtils.ParseExpression(expressionTextLeft);
            var expressionRight = ParseUtils.ParseExpression(expressionTextRight);
            Assert.IsTrue(expressionLeft.IsEqual(expressionRight));
        }

        [TestCase("x")]
        [TestCase("y - 3")]
        [TestCase("3  - y")]
        [TestCase("3  + y + x * n * y * (12 + e)")]
        [TestCase("x")]
        [TestCase("x^y + 12*u*u - r")]
        [TestCase("x^y ^(3+3 - 3 * r)")]
        [TestCase("sin(r^r^t)")]
        [TestCase("cos(r^r^t)")]
        [TestCase("tg(r^r^t)")]
        [TestCase("-(x^y + 12*u*u-i - r)")]
        [TestCase("-sin(cos(7*m))*cos(r^3 - 12)")]
        [TestCase("-sin(m)^fg*y")]
        [TestCase("cos * 3 - sin(x)")]
        [TestCase("-5")]
        [Test]
        public void IsEqual_CloneExpressionsEqual_Test(string expressionTextLeft)
        {
            var expressionLeft = ParseUtils.ParseExpression(expressionTextLeft);
            Assert.IsTrue(expressionLeft.IsEqual(expressionLeft.Clone()));
        }
    }
}
